package raft

// 投票相关RPC

type RequestVoteArgs struct {
	// Your data here (2A, 2B).
	Term         int
	CandidateId  int
	LastLogIndex int
	LastLogTerm  int
}

type RequestVoteReply struct {
	// Your data here (2A).
	Term        int
	VoteGranted bool
}

func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply) {
	// Your code here (2A, 2B).
	rf.mu.Lock()
	defer func() {
		rf.mu.Unlock()
		rf.persist()
	}()
	//DPrintf("%v 收到投票请求\n", rf.me)
	if args.Term < rf.term {
		//Reply false if term < currentTerm (§5.1)
		reply.VoteGranted = false
		reply.Term = rf.term
		return
	} else {
		if args.Term > rf.term {
			rf.term = args.Term
			rf.votedFor = -1
		}
		reply.Term = rf.term
		// If votedFor is null or candidateId, and candidate’s log is at
		// least as up-to-date as receiver’s log, grant vote (§5.2, §5.4)
		flag := false
		if rf.votedFor == -1 {
			lastLogIndex, lastLogTerm := rf.getLastLogIndexAndTerm()
			if lastLogTerm < args.LastLogTerm {
				flag = true
			} else if lastLogTerm == args.LastLogTerm && lastLogIndex <= args.LastLogIndex {
				flag = true
			}
		}
		if flag {
			reply.VoteGranted = true
			rf.votedFor = args.CandidateId
			rf.changeState <- 0
			//fmt.Printf("%v 投票给 %v \n", rf.me, args.CandidateId)
		} else {
			reply.VoteGranted = false
		}
	}
}
